#include "xdecode.h"
#include "xvideo_view.h"
#include <fstream>
#include <iostream>
#include <string>
#ifdef main
#undef main
#endif // !main
using namespace std;
extern "C" { // 指定函数是c语言函数，函数名不包含重载标注
// 引用ffmpeg头文件
#include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
}
int main(int argc, char *argv[]) {
  av_log_set_level(AV_LOG_DEBUG);
  auto view = XVideoView::Create();
  // 1 分割h264 存入AVPacket
  //  ffmpeg -i v1080.mp4 -s 400x300 test.h264
  string filename = "test.h264";
  ifstream ifs(filename, ios::binary);
  if (!ifs)
    return -1;
  unsigned char inbuf[4096] = {0};
  AVCodecID codec_id = AV_CODEC_ID_H264;
  XDecode de;
  // 根据编码器创建解码器上下文
  auto c = de.Create(codec_id, false);
  de.set_c(c);
  de.InitHW(AV_HWDEVICE_TYPE_DXVA2);
  de.Open();
  // 分割上下文
  auto parser = av_parser_init(codec_id);
  auto pkt = av_packet_alloc();
  auto frame = av_frame_alloc();
  auto begin = NowMs();
  int count = 0; // 解码统计
  bool is_init_win = false;

  while (!ifs.eof()) {
    ifs.read((char *)inbuf, sizeof(inbuf));
    int data_size = ifs.gcount(); // 读取的字节数
    if (data_size <= 0) {
      break;
    }
    // if (ifs.eof()) {
    //   break;
    // }
    auto data = inbuf;
    while (data_size > 0) // 一次有多帧数据
    {
      // 通过0001 截断输出到AVPacket 返回帧大小
      int ret = av_parser_parse2(parser, c, &pkt->data, &pkt->size, // 输出
                                 data, data_size,                   // 输入
                                 AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
      data += ret;
      data_size -= ret; // 已处理
      if (pkt->size) {
        // 发送packet到解码线程
        if (!de.Send(pkt)) {
          break;
        }
        // 获取多帧解码数据
        while (de.Receive(frame)) {
          /// 第一帧初始化窗口
          if (!is_init_win) {
            is_init_win = true;
            view->Init(frame->width, frame->height,
                       (XVideoView::Format)frame->format);
          }
          view->DrawFrame(frame);
          count++;
          auto cur = NowMs();
          if (cur - begin >= 1000) // 1秒钟计算一次
          {
            cout << "\nfps = " << count << endl;
            count = 0;
            begin = cur;
          }
        }
      }
    }
  }
  /// 取出缓存数据
  auto frames = de.End();
  for (auto f : frames) {
    view->DrawFrame(f);
    av_frame_free(&f);
  }
  frames.clear();
  av_parser_close(parser);
  avcodec_free_context(&c);
  av_frame_free(&frame);
  av_packet_free(&pkt);

  return 0;
}
